# _*_ coding: utf-8 _*_
#!/usr/bin/env python

#      ___________________
#  ___| Modulbeschreibung \_________________________________________________________________________
# | Ist für das Menü zuständig. Es gibt Untermenüs und es soll späte vielleicht noch um Ein-
# | stellungsmöglichkeiten für Grafik, Netzwerk, ect. erweitert werden.
# |__________________________________________________________________| Zuständigkeit [Hendrik] |____

import sys, os
import pygame
import time

# Aktualisierungsrate des Menüs
FPS_LIMIT	= 25

def addWorkPath(filename):
	"""Aus Portabilitätsgruenden wie relativen Pfadangaben unter verschiedenen Systemen gehandhabt werden. Haengt das Arbeitsverzeichnis vor den übergebenen Dateinamen"""
	return os.path.join(os.path.dirname(sys.argv[0]), 'data', filename)

class IpField(object):
	"""Eingabefeld für die IP-Adressen"""
	def __init__(self, parent, default = ''):
		"""Konstruktor"""
		self.parent		= parent
		self.surface	= pygame.Surface((100, 20))
		self.ip_address	= default
	
	def hitKey(self, key):
		"""Verarbeitet Tasteneingaben"""
		# Zeichen loeschen
		if key == pygame.K_BACKSPACE:
			if self.ip_address:
				self.ip_address = self.ip_address[:-1]
		# Punkt schreiben
		elif key == pygame.K_PERIOD:
			splited	= self.ip_address.split('.')
			# Nur wenn davor schon eine Zahl steht und es danach nur max. drei Punkte gibt
			if len(splited[-1]) and len(splited) < 4:
				self.ip_address += '.'
		# Zahl schreiben
		elif pygame.key.name(key) in ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'):
			splited	= self.ip_address.split('.')
			# Zahlentrippel komplett
			if len(splited[-1]) > 2:
				# Wenn viertes Zahlentrippel, dann nichts mehr schreiben...
				if len(splited) > 3:
					return
				# ... sonst Trennpunkt einfuegen
				self.ip_address += '.'
			self.ip_address += pygame.key.name(key)
	
	def isComplete(self):
		"""Gibt True zurück, wenn die bisher eingegebene IP-Adresse, komplett ist"""
		return len(self.ip_address.split('.')) == 4
	
	def getSurface(self):
		"""Gibt die Surface des Controls zurük"""
		self.surface.fill((0, 0, 0))
		pygame.draw.rect(self.surface, (255, 10, 10), (0, 0, self.surface.get_width(), self.surface.get_height()), 1)
		self.surface.blit(self.parent.font.render('%s' % self.ip_address, True, (255, 10, 10)), (5, 5))
		return self.surface


class Menu(object):
	def __init__(self, game, race):
		"""Konstruktor"""
		self.game	= game
		self.screen	= game.screen
		self.clock	= game.clock
		self.sounds	= {	'click':	pygame.mixer.Sound(addWorkPath('data/sounds/click.ogg')),
						'click2':	pygame.mixer.Sound(addWorkPath('data/sounds/click2.ogg'))}
		
		#Das Netzwer muss schon initialisiert werden um eine Verbindung zum Server aufbauen zu koennen
		self.race = race
		self.showMainMenu()
	
	def showMainMenu(self):
		"""Zeigt das Hauptmenü, wird automatisch vom Konstruktor aufgerufen"""
		self.big_font	= pygame.font.Font(addWorkPath('Visitor_TT2_BRK.ttf'), 25)
		self.font		= pygame.font.Font(addWorkPath('Visitor_TT2_BRK.ttf'), 12)
		menue_section	= [0, 1]#, 2]
		selection_index	= 0#4
		key_down_frames	= {	'up':	0,
							'down':	0}
		anim_counter	= 1
		while True:
			menue		=	[	('Main',					'Hauptmenue',					(
									('Singleplayer',		'Einzelspielermodus',			None),
									('Multiplayer',			'Mehrspielermodus',				(
										('Join game',		'Einem Spiel beitreten',		self.showJoinGameWindow),
										('Create game',		'Einen neuen Server erstellen',	self.showCreateGameWindow),
										('< Back',			'Zurueck ins Hauptmenue',		-1)
									)),
									('Options',				'Spieleinstellungen',			(
										('Graphic',			'Grafikeinstellungen',			(
											('Nebel',		'Nebeleffekte aktivieren',		None),
											('Resolution',	'Bildschirmaufloesung aendern',	None),
											('< Back',		'Zurueck zu den Optionen',		-1)
										)),
										('Sound',			'Soundeinstellungen',			None),
										('Network',			'Netzwerk konfigurieren',		None),
										('Misc',			'Diverses',						None),
										('Credits',			'Ueber dieses Programm',		self.showCredits),
										('< Back',			'Zurueck ins Hauptmenue',		-1)
									)),
									('Quit',				'Spiel verlassen',				self.quitGame)
								))
							]
			
			active_menue	= menue
			menue_path		= '>> '
			menue_name		= ''
			# Dem Menüpfad einzeln folgen
			for sub_menue in menue_section:
				menue_name		= active_menue[sub_menue][0]
				menue_path		+= menue_name + '/'
				active_menue	= active_menue[sub_menue][2]
			
			# Schleife für die Einblendfunktion der Menüs
			while anim_counter:
				anim_counter	-= 1
				self.screen.fill((0, 0, 0))
				self.screen.blit(self.big_font.render(menue_name, True, (255, 10, 10)), (10, 10 - anim_counter * 2))
				self.screen.blit(self.font.render(menue_path, True, (255, 10, 10)), (10, 30 - anim_counter * 2))
				
				counter = 0
				# Jeden Menüpunkt des aktuellen Untermenüs durchgehen
				for menue_point in active_menue:
					if counter == selection_index:
						color = (255, 255, 10)
					elif menue_point[2] == None:
						color = (160, 80, 80)
					else:
						color = (255, 10, 10)
					if menue_point[2] == -1:
						self.screen.blit(self.font.render(menue_point[0], True, color), (10 - anim_counter * 2, 80 + counter * 15))
					else:
						self.screen.blit(self.font.render(menue_point[0], True, color), (10 - anim_counter * 2, 70 + counter * 15))
					counter += 1
				
				# Den Infostring am unteren Bildschirmrand einblenden
				infostring = active_menue[selection_index][1]
				if active_menue[selection_index][2] == None:
					infostring = ' /!\ DISABLED - ' + infostring
				self.screen.blit(self.font.render('[ %s ]' % infostring, True, (255, 10, 10)), (10, 200 + anim_counter * 2))
				
				pygame.display.flip()
				self.clock.tick(FPS_LIMIT)
			
			anim_counter	= 1
			
			# Nachschen ob neue Events (Tastendrücke) in der Event-Qeue sind
			for event in pygame.event.get():
				# Fenster schließen
				if event.type == pygame.QUIT:
					self.quitGame()
				# Taste gedrückt
				if event.type == pygame.KEYDOWN:
					# Escape geht eine Menüebene nach oben, bzw verlässt das Programm im Hauptmenü
					if event.key == pygame.K_ESCAPE:
						self.sounds['click2'].play()
						if True: #len(menue_section) == 1:
							self.quitGame()
						menue_section.pop()
						selection_index			= 0
						anim_counter			= 10
					
					# Es wurde ein Menüpunkt ausgewählt
					elif event.key == pygame.K_RETURN:
						# Menüpunkt ist Untermenü
						if type(active_menue[selection_index][2]) == tuple:
							self.sounds['click2'].play()
							menue_section.append(selection_index)
							selection_index		= 0
							anim_counter		= 10
						else:
							# Eine Ebene nach oben
							if active_menue[selection_index][2] == -1:
								self.sounds['click2'].play()
								menue_section.pop()
								selection_index	= 0
								anim_counter	= 10
							# Menüpunkt ohne Funktion (ausgegraut)
							elif active_menue[selection_index][2] != None:
								self.sounds['click2'].play()
								active_menue[selection_index][2]()
					# Den Counter für die Dauer des Tastendruckes um 1 erhöhen (für Key-Repeat)
					elif event.key == pygame.K_UP:
						key_down_frames['up']	= 1
					elif event.key == pygame.K_DOWN:
						key_down_frames['down']	= 1
				# Taste losgelassen
				elif event.type == pygame.KEYUP:
					if event.key == pygame.K_UP:
						key_down_frames['up']	= 0
					elif event.key == pygame.K_DOWN:
						key_down_frames['down']	= 0
			
			if key_down_frames['up']:
				if key_down_frames['up'] == 1 or (key_down_frames['up'] > 8 and not key_down_frames['up'] % 2):
					self.sounds['click'].play()
					if selection_index > 0:
						selection_index -= 1
					else:
						selection_index = len(active_menue) - 1
				key_down_frames['up']			+= 1
			elif key_down_frames['down']:
				if key_down_frames['down'] == 1 or (key_down_frames['down'] > 8 and not key_down_frames['down'] % 2):
					self.sounds['click2'].play()
					if selection_index < len(active_menue) - 1:
						selection_index += 1
					else:
						selection_index = 0
				key_down_frames['down']			+= 1
	
	def showJoinGameWindow(self):
		"""Das Fenster für den Spielebeitritt anzeigen"""
		surf			= pygame.Surface((self.screen.get_width(), self.screen.get_height()))
		surf.set_alpha(150)
		self.screen.blit(surf, (0, 0))
		anim_counter	= 0
		pygame.draw.rect(self.screen, (255, 10, 10), (50, 50, 400, 200), 1)
		ip_field		= IpField(self, '192.168.178.20')
		status			= 'ip-field'
		connect = False
		
		pygame.key.set_repeat(500, 100)
		while True:
			# Auf Tastendruecke reagieren
			for event in pygame.event.get():
				if event.type == pygame.QUIT:
					self.quitGame()
				if event.type == pygame.KEYDOWN:
					if event.key == pygame.K_ESCAPE:
						pygame.key.set_repeat()
						return
					elif event.key == pygame.K_RETURN:
						if status == 'ip-field':
							if ip_field.isComplete():
								status = 'waiting'
							else:
								status = 'bad-ip'
					else:
						ip_field.hitKey(event.key)
			
			self.screen.fill((0, 0, 0), (51, 51, 398, 198))
			self.screen.blit(self.big_font.render('Join game', True, (255, 10, 10)), (60, 60))
			if status == 'ip-field':
				self.screen.blit(self.font.render('Bitte IP-Adresse des Servers angeben:', True, (255, 10, 10)), (60, 95))
				self.screen.blit(ip_field.getSurface(), (280, 90))
			elif status == 'bad-ip' or status == 'bad-ip server':
				self.screen.blit(self.font.render('Die angegebene IP-Adresse ist ungueltig!', True, (255, 10, 10)), (60, 95))
				pygame.display.flip()
				pygame.time.wait(2000)
				status = 'ip-field'
			elif status == 'full':
				self.screen.blit(self.font.render('Das angegebene Spiel ist voll oder laeuft bereits!', True, (255, 10, 10)), (60, 95))
				pygame.display.flip()
				pygame.time.wait(2000)
				status = 'ip-field'
			
			elif status == 'waiting':
				
				if connect != True:
					self.race.connectToServer(self.race,ip_field.ip_address)
					time.sleep(1)
					if self.race.network.conSucessfull():
						connect = True
					else: 
						status = 'full'
					
				players = self.race.network.getPlayerInf()#[('Jannik', '127.0.0.1'), ('Hendrik', '127.0.0.1')]
				counter = 0

				for player in players:
					if player != None:
						self.screen.blit(self.font.render('%.20s\t %s' % (player[0], player[1]), True, (255, 10, 10)), (60, 95 + counter * 12))
						counter += 1
					
				self.screen.blit(self.font.render('Bitte warten...', True, (255, 10, 10)), (60, 95 + counter * 12))
				if self.race.network.getRaceState() == "start":
					self.game.startGame(self.race)
			
			pygame.display.flip()
			self.clock.tick(FPS_LIMIT)
	
	def showCreateGameWindow(self):
		'''Zeigt das Fenster zur Erstellung eines Rennens an'''
		surf			= pygame.Surface((self.screen.get_width(), self.screen.get_height()))
		surf.set_alpha(150)
		self.screen.blit(surf, (0, 0))
		anim_counter	= 0
		pygame.draw.rect(self.screen, (255, 10, 10), (50, 50, 400, 200), 1)
		ip_field		= IpField(self, '192.168.178.20')
		status			= 'ip-field'
		connect = False
		
		pygame.key.set_repeat(500, 100)
		while True:
			# Auf Tastendruecke reagieren
			for event in pygame.event.get():
				if event.type == pygame.QUIT:
					self.quitGame()
				if event.type == pygame.KEYDOWN:
					if event.key == pygame.K_ESCAPE:
						pygame.key.set_repeat()
						
					elif event.key == pygame.K_RETURN:
						if status == 'waiting':
							self.race.network.startRace()
						if status == 'ip-field':
							if ip_field.isComplete():
								status = 'waiting'
							else:
								status = 'bad-ip'
					else:
						ip_field.hitKey(event.key)
			
			self.screen.fill((0, 0, 0), (51, 51, 398, 198))
			self.screen.blit(self.big_font.render('Create gameserver', True, (255, 10, 10)), (60, 60))
			if status == 'ip-field':
				self.screen.blit(self.font.render('Bitte eigene IP-Adresse angeben:', True, (255, 10, 10)), (60, 95))
				self.screen.blit(ip_field.getSurface(), (280, 90))
			elif status == 'bad-ip' or status == 'bad-ip server':
				self.screen.blit(self.font.render('Die angegebene IP-Adresse ist ungueltig!', True, (255, 10, 10)), (60, 95))
				pygame.display.flip()
				pygame.time.wait(2000)
				status = 'ip-field'
			elif status == 'full':
				self.screen.blit(self.font.render('Ueberpruefen sie bitte die IP und ihre Firewalleinstellungen.', True, (255, 10, 10)), (60, 95))
				pygame.display.flip()
				pygame.time.wait(2000)
				status = 'ip-field'			
			elif status == 'waiting':
				self.screen.blit(self.font.render('Server-IP ist: %s' % ip_field.ip_address, True, (255, 255, 10)), (280, 67))
				
				if connect != True:
					self.race.network.runServer(ip_field.ip_address)
					time.sleep(1)
										
					self.race.connectToServer(self.race,ip_field.ip_address)
					time.sleep(1)
					if self.race.network.conSucessfull():
						connect = True
					else: 
						status = 'full'
						self.race.network.stopServer()
					
				players = self.race.network.getPlayerInf()#[('Jannik', '127.0.0.1'), ('Hendrik', '127.0.0.1')]
				counter = 0

				for player in players:
					if player != None:
						self.screen.blit(self.font.render('%.20s\t %s' % (player[0], player[1]), True, (255, 10, 10)), (60, 95 + counter * 12))
						counter += 1
					
				self.screen.blit(self.font.render('Bitte warten...', True, (255, 10, 10)), (60, 95 + counter * 12))
				if self.race.network.getRaceState() == "start":
					print "starten"
					self.game.startGame(self.race)
					
				self.screen.blit(self.font.render('Zum Starten [Return] druecken', True, (160, 80, 80)), (60, 230))
			
			pygame.display.flip()
			self.clock.tick(FPS_LIMIT)
			
		#surf = pygame.Surface((self.screen.get_width(), self.screen.get_height()))
		#surf.set_alpha(150)
		#self.screen.blit(surf, (0, 0))
		#anim_counter	= 0
		#pygame.draw.rect(self.screen, (255, 10, 10), (50, 50, 400, 200), 1)
		#while True:
			#self.screen.fill((0, 0, 0), (51, 51, 398, 198))
			#self.screen.blit(self.big_font.render('Create gameserver', True, (255, 10, 10)), (60, 60))
			#self.screen.blit(self.font.render('Deine Adresse ist 192.168.0.23', True, (255, 255, 10)), (280, 65))
			#self.screen.blit(self.font.render('-----Mitspielerliste-----', True, (255, 10, 10)), (60, 110))
			#players = [('Jannik', '127.0.0.1'), ('Hendrik', '127.0.0.1')]
			#counter = 0
			#for player in players:
				#self.screen.blit(self.font.render('%.10s\t %s' % (player[0], player[1]), True, (255, 10, 10)), (60, 130 + counter * 15))
				#counter += 1
			#self.screen.blit(self.font.render('Bitte warten %s' % ('.' * (anim_counter / 9)), True, (255, 10, 10)), (60, 130 + counter * 15))
			
			#self.screen.blit(self.font.render('Zum Starten [Return] drücken (nicht genug Mitspieler!)', True, (160, 80, 80)), (60, 230))
			
			#pygame.display.flip()
			#self.clock.tick(FPS_LIMIT)
			#for event in pygame.event.get():
				#if event.type == pygame.QUIT:
					#self.quitGame()
				#if event.type == pygame.KEYDOWN:
					#if event.key == pygame.K_ESCAPE:
						#return
			#if anim_counter < 32:
				#anim_counter += 1
			#else:
				#anim_counter = 0
	
	def showCredits(self):
		'''Zeigt die Credits an'''
		surf = pygame.Surface((self.screen.get_width(), self.screen.get_height()))
		surf.set_alpha(15)
		anim_counter	= 15
		while anim_counter:
			self.screen.blit(surf, (0, 0))
			pygame.display.flip()
			self.clock.tick(FPS_LIMIT)
			anim_counter -= 1
		
		pygame.draw.rect(self.screen, (255, 10, 10), (50, 50, 400, 200), 1)
		while True:
			self.screen.fill((0, 0, 0), (51, 51, 398, 198))
			self.screen.blit(self.big_font.render('Credits', True, (255, 10, 10)), (60, 60))
			
			self.screen.blit(self.font.render('< Grafik / Menue-Programmierung >', True, (255, 10, 10)), (60, 90))
			self.screen.blit(self.font.render('< Maps und Grafiken >', True, (255, 10, 10)), (60, 100))
			self.screen.blit(self.font.render('< Spiellogik >', True, (255, 10, 10)), (60, 110))
			self.screen.blit(self.font.render('< Hauptprogramm und 3D >', True, (255, 10, 10)), (60, 120))
			self.screen.blit(self.font.render('Hendrik Leibrandt', True, (255, 10, 10)), (260, 90))
			
			self.screen.blit(self.font.render('< Netzwerk-Programmierung >', True, (255, 10, 10)), (60, 140))
			self.screen.blit(self.font.render('< Musik und Sounds >', True, (255, 10, 10)), (60, 150))
			self.screen.blit(self.font.render('< Spiellogik >', True, (255, 10, 10)), (60, 160))
			self.screen.blit(self.font.render('Jannik Waschkau', True, (255, 10, 10)), (260, 140))
			
			#self.screen.blit(self.font.render('< Danke an die Tester >', True, (255, 10, 10)), (60, 130))
			#self.screen.blit(self.font.render('???', True, (255, 10, 10)), (250, 130))
			#self.screen.blit(self.font.render('???', True, (255, 10, 10)), (250, 145))
			
			self.screen.blit(self.font.render('* Grafiken, Sounds, Musik sind teilweise aus "Super Mario Kart"', True, (255, 10, 10)), (60, 210))
			self.screen.blit(self.font.render('Copyright by NINTENDO', True, (255, 10, 10)), (60, 220))
			#self.screen.blit(self.font.render('GPL-Lizens - 2009 Hendrik Leibrandt & Jannik Waschkau - DQI05', True, (255, 10, 10)), (60, 220))
			
			self.screen.blit(self.font.render('[ Beliebige Taste zum Verlassen druecken ]', True, (160, 80, 80)), (60, 235))
			self.screen.blit(self.font.render('2009 - Unter GPL-Liz.', True, (255, 10, 10)), (330, 250))
			
			pygame.display.flip()
			self.clock.tick(FPS_LIMIT)
			for event in pygame.event.get():
				if event.type == pygame.QUIT:
					self.quitGame()
				if event.type == pygame.KEYDOWN:
					return
			anim_counter += 1

	def quitGame(self):
		self.game.quitGame()


if __name__ == '__main__':
	main = Game()
